import tkinter as tk
from tkinter import messagebox
import ipaddress

def calculate():
    ip_type = ip_type_var.get()
    ip_addr = entry_addr.get().strip()
    prefix = prefix_var.get()
    try:
        if ip_type == "IPv4":
            network = ipaddress.IPv4Network(f"{ip_addr}/{prefix}", strict=False)
            # 计算反掩码
            netmask = network.netmask
            wildcard = ipaddress.IPv4Address(int(netmask) ^ 0xFFFFFFFF)
        else:
            network = ipaddress.IPv6Network(f"{ip_addr}/{prefix}", strict=False)
        first_host = network.network_address + 1 if network.num_addresses > 1 else network.network_address
        last_host = network.network_address + (network.num_addresses - 1)
        result = (
            f"网络地址: {network.network_address}\n"
            f"子网掩码: {network.netmask}\n"
            f"前缀长度: /{network.prefixlen}\n"
            f"可用主机数: {network.num_addresses}\n"
        )
        if ip_type == "IPv4":
            result += f"反掩码: {wildcard}\n"
        result += (
            f"第一个可用地址: {first_host}\n"
            f"最后一个可用地址: {last_host}\n"
        )
        text_result.config(state='normal')
        text_result.delete(1.0, tk.END)
        text_result.insert(tk.END, result)
        text_result.config(state='disabled')
    except Exception as e:
        text_result.config(state='normal')
        text_result.delete(1.0, tk.END)
        text_result.insert(tk.END, f"输入有误: {e}")
        text_result.config(state='disabled')

def on_scale(val):
    prefix = int(float(val))
    prefix_var.set(prefix)
    entry_prefix.delete(0, tk.END)
    entry_prefix.insert(0, str(prefix))
    calculate()

def on_entry_change(event):
    try:
        prefix = int(entry_prefix.get())
        if 0 <= prefix <= (32 if ip_type_var.get() == "IPv4" else 128):
            scale_prefix.set(prefix)
            prefix_var.set(prefix)
            calculate()
    except:
        pass

def on_ip_type_change():
    ip_type = ip_type_var.get()
    if ip_type == "IPv4":
        entry_addr.delete(0, tk.END)
        entry_addr.insert(0, "192.168.1.1")
        scale_prefix.config(from_=0, to=32)
        entry_prefix.delete(0, tk.END)
        entry_prefix.insert(0, "24")
        prefix_var.set(24)
        scale_prefix.set(24)
    else:
        entry_addr.delete(0, tk.END)
        entry_addr.insert(0, "2001::1")
        scale_prefix.config(from_=0, to=128)
        entry_prefix.delete(0, tk.END)
        entry_prefix.insert(0, "64")
        prefix_var.set(64)
        scale_prefix.set(64)
    calculate()

root = tk.Tk()
root.title("IP子网掩码计算器")

# IP类型选择（单选按钮）
tk.Label(root, text="IP类型:").grid(row=0, column=0, padx=5, pady=5, sticky='e')
ip_type_var = tk.StringVar(value="IPv6")
radio_ipv4 = tk.Radiobutton(root, text="IPv4", variable=ip_type_var, value="IPv4", command=on_ip_type_change)
radio_ipv6 = tk.Radiobutton(root, text="IPv6", variable=ip_type_var, value="IPv6", command=on_ip_type_change)
radio_ipv4.grid(row=0, column=1, padx=2, pady=5, sticky='w')
radio_ipv6.grid(row=0, column=1, padx=60, pady=5, sticky='w')

tk.Label(root, text="IP地址:").grid(row=1, column=0, padx=5, pady=5, sticky='e')
entry_addr = tk.Entry(root, width=40)
entry_addr.grid(row=1, column=1, padx=5, pady=5)
entry_addr.insert(0, "2001::1")  # 默认示例

tk.Label(root, text="前缀长度:").grid(row=2, column=0, padx=5, pady=5, sticky='e')

prefix_var = tk.IntVar(value=64)
entry_prefix = tk.Entry(root, width=6)
entry_prefix.grid(row=2, column=1, padx=5, pady=5, sticky='w')
entry_prefix.insert(0, "64")
entry_prefix.bind("<KeyRelease>", on_entry_change)

scale_prefix = tk.Scale(root, from_=0, to=128, orient=tk.HORIZONTAL, variable=prefix_var, command=on_scale, length=300)
scale_prefix.set(64)
scale_prefix.grid(row=3, column=0, columnspan=2, padx=5, pady=5)

btn_calc = tk.Button(root, text="计算", command=calculate)
btn_calc.grid(row=4, column=0, columnspan=2, pady=10)

text_result = tk.Text(root, width=60, height=10, state='disabled')
text_result.grid(row=5, column=0, columnspan=2, padx=5, pady=5)

# 初始化时自动计算
calculate()

root.mainloop()